package com.zbj.homemade.spring.aop.proxy;

import com.zbj.homemade.spring.aop.exception.AopException;
import com.zbj.homemade.spring.aop.interceptor.MethodInterceptor;
import com.zbj.homemade.spring.aop.invocation.SimpleInvocation;
import com.zbj.homemade.spring.utils.ClassUtil;
import com.zbj.homemade.spring.utils.CollectionsUtil;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.List;
import java.util.Map;

/**
 * |                    .  ’   *   ‘  .
 * |               _6                    "     o0000o
 * |  o00o _    .%                         %. o0000000o
 * | o000000o.:                              :(0000000o
 * | o00000os                                  .000000o
 * |  o0000/     <b>不了不了,改需求真的伤身体</>   .000o
 * |    o0o                                       .0o
 * |     y        <b>我认为源代码,就是SkrSkr</>     .
 * |    y                                           ,
 * |   y          <b>小熊猫保佑,代码永不修改</>        ,
 * |   p                            .                 .
 * |   p                           @@.                .
 * |    y                        ;@@@;               .
 * |    \                       ;@@@@;.@.          ,;S
 * |     、                     .@@@@@@;       ,@@@@@
 * |     @\.            .****...*@@@@;     .@@@@@@@@@@@.
 * |    @@@@\.     . @@@@@@@@@@@@@@@;    .@@@@@@@@@@@@@@@.
 * |   @@@@@@@@@.@@@@@@@@@@@@@@@@;   .@@@@@@@@@@@@@@@@@@@@@.
 * |  @@@@@@..@@@@..@@@@@@..@@@@@ .@@...@@@@@..@@..@@@@@..@@.
 * | @@@@@@@@..@..@@@@@@@@@@@@@;.@@@..@..@@@..@@....@@@..@@@@.
 * |@y@@@@@@@@..@@@@@@@@..@@@@i@@@@..@@@..@..@@..@@..@..@@@@n@.
 * |@n@@@@@@@..@@@@@@@@..@@@@@@@@@..@@@@@...@@..@@@@...@@@@@n@@.
 * |@@@@@@@@..@@@@@@@@..@@@@@@@@@..@@@@@@@.@@..@@@@@..@@@@@@@@@@.
 * |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@.
 *
 * @program: principle
 * @description: 执行代理
 * @author: Yinn
 * @create: 2019-03-08 11:32
 **/
public class JdkInvocationHandler implements InvocationHandler, AopProxy {

    private final Object bean;

    private final Map<Method, List<MethodInterceptor>> methodListMap;

    public JdkInvocationHandler(Object bean, Map<Method, List<MethodInterceptor>> methodListMap) {
        this.bean = bean;
        this.methodListMap = methodListMap;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        Method cacheKey = bean.getClass().getMethod(method.getName(), method.getParameterTypes());

        if (cacheKey == null){
            throw new AopException("在实现类中找到对应方法!");
        }


        List<MethodInterceptor> methodInterceptors = methodListMap.get(cacheKey);

        if (!CollectionsUtil.isEmpty(methodInterceptors)) {

            SimpleInvocation simpleInvocation = new SimpleInvocation(methodInterceptors, method, proxy, bean, args);

            return simpleInvocation.proceed();
        }

        return method.invoke(bean, args);
    }

    public Object getProxy() {
        return Proxy.newProxyInstance(ClassUtil.getDefaultClassLoader(), bean.getClass().getInterfaces(), this);
    }
}
